"""
文件上传服务模块
"""

import logging
import requests
import json
import time

from jlpay.model.upload import (
    ImageUploadRequest, 
    VideoUploadRequest, 
    PdfUploadRequest, 
    FileUploadResponse
)
from jlpay.exception.exceptions import HttpExecutionException, SignVerifyException
from jlpay.utils.sm_utils import sm2_sign, sm2_verify, generate_random_string
from jlpay.core.sign import SignVerifierManager

# 创建日志记录器
logger = logging.getLogger("jlpay.service.file")

class FileService:
    """文件服务类 - 独立的文件传输服务"""
    
    def __init__(self, config):
        """
        初始化文件服务
        
        Args:
            config: OrgConfig实例
        """
        self.config = config
        self.sign_verifier = SignVerifierManager.get_verifier(config)
    
    def get_api_url(self, request_class, api_path=None):
        """
        获取API URL
        
        Args:
            request_class: 请求类
            api_path: 接口路径
            
        Returns:
            完整的API URL
        """
        if api_path:
            return f"{self.config.url}{api_path}"
        
        # 获取请求对象
        request_instance = request_class()
        
        # 优先使用get_api_uri方法
        if hasattr(request_instance, 'get_api_uri'):
            return f"{self.config.url}{request_instance.get_api_uri()}"
        
        # 使用API_PREFIX和API_URI属性组合
        api_prefix = getattr(request_instance, 'API_PREFIX', '')
        api_uri = getattr(request_instance, 'API_URI', '')
        
        return f"{self.config.url}{api_prefix}{api_uri}"
    
    def post(self, request, response_class):
        """
        发送POST请求
        
        Args:
            request: 请求对象
            response_class: 响应类
            
        Returns:
            响应对象
        """
        # 构建完整URL
        url = self.get_api_url(request.__class__)
        logger.debug(f"文件上传请求URL: {url}")
        
        # 获取URI部分用于签名
        uri = url.split('.com')[1] if '.com' in url else url.split('://', 1)[1].split('/', 1)[1]
        
        try:
            # 准备文件数据
            files = {'file': request.file} if hasattr(request, 'file') else None
            
            # 准备表单数据
            data = {}
            if hasattr(request, 'meta'):
                data['meta'] = request.meta
            
            # 使用meta进行签名（而不是body）
            meta_for_sign = request.meta if hasattr(request, 'meta') and request.meta else "{}"
            sign_value, timestamp, nonce = self.sign_verifier.sign("POST", uri, meta_for_sign)
            
            # 添加认证和签名头
            headers = {
                'x-jlpay-appid': self.config.app_id,
                'x-jlpay-nonce': nonce,
                'x-jlpay-timestamp': timestamp,
                'x-jlpay-sign-alg': 'SM3WithSM2WithDer',
                'x-jlpay-sign': sign_value
            }
            
            logger.debug("=== 文件上传请求信息 ===")
            logger.debug(f"请求URL: {url}")
            logger.debug(f"请求方法: POST")
            logger.debug("请求头:")
            for key, value in headers.items():
                logger.debug(f"  {key}: {value}")
            logger.debug(f"表单数据: {json.dumps(data, ensure_ascii=False)}")
            logger.debug(f"文件数据: {'已设置' if files else '未设置'}")
            logger.debug("=========================")
            
            # 发送请求
            response = requests.post(
                url, 
                files=files,
                data=data,
                headers=headers
            )
            
            # 检查请求是否成功
            response.raise_for_status()
            
            # 解析响应
            response_data = response.json()
            logger.debug(f"文件上传响应: {json.dumps(response_data, ensure_ascii=False)}")
            
            # 验证响应签名
            if 'x-jlpay-sign' in response.headers:
                self.sign_verifier.verify(
                    "POST",
                    uri,
                    response.headers.get("x-jlpay-timestamp"),
                    response.headers.get("x-jlpay-nonce"),
                    response.text,
                    response.headers.get("x-jlpay-sign")
                )
            
            # 创建响应对象
            return response_class(response_data)
            
        except requests.exceptions.RequestException as e:
            logger.error(f"文件上传请求失败: {str(e)}")
            raise HttpExecutionException(f"文件上传请求失败: {str(e)}", e)
        except json.JSONDecodeError as e:
            logger.error(f"解析响应JSON失败: {str(e)}, 原始响应: {response.text[:200]}...")
            raise HttpExecutionException(f"解析响应JSON失败: {str(e)}", e)
        except SignVerifyException as e:
            logger.error(f"响应签名验证失败: {str(e)}")
            raise e
        except Exception as e:
            logger.error(f"文件上传过程中发生未知错误: {str(e)}")
            raise HttpExecutionException(f"文件上传过程中发生未知错误: {str(e)}", e)
    
    def upload_image(self, request):
        """
        上传图片
        
        Args:
            request: ImageUploadRequest实例
            
        Returns:
            FileUploadResponse实例
        """
        return self.post(request, FileUploadResponse)
    
    def upload_video(self, request):
        """
        上传视频
        
        Args:
            request: VideoUploadRequest实例
            
        Returns:
            FileUploadResponse实例
        """
        return self.post(request, FileUploadResponse)
    
    def upload_pdf(self, request):
        """
        上传PDF
        
        Args:
            request: PdfUploadRequest实例
            
        Returns:
            FileUploadResponse实例
        """
        return self.post(request, FileUploadResponse) 